#include "Model/WeeklyCalendarRule.hpp"

namespace Model
{

WeeklyCalendarRule::WeeklyCalendarRule()
: weekdayMap_(0)
{
}

// ---------------------------------------------------------------------------------------------------------------------

void WeeklyCalendarRule::addWeekDay( unsigned int weekDay )
{
	assert( weekDay > 0 && weekDay <= 7);
	weekdayMap_ |= (1 << weekDay);
}

// ---------------------------------------------------------------------------------------------------------------------

void WeeklyCalendarRule::removeWeekDay( unsigned int weekDay )
{
	weekdayMap_ &= ~(1 << weekDay);
}

// ---------------------------------------------------------------------------------------------------------------------

void WeeklyCalendarRule::getPeriods( const Calendar::Time& start, const Calendar::Time& end, Calendar::PeriodSet& out )
{
	// TODO: Improve code: use date iterators

	assert( out.empty());
	assert( start < end);
	Calendar::PeriodSet periods;

	Calendar::Date curDate = start.date(),
		endDate = end.date();
	while( curDate <= endDate)
	{
		unsigned int wd = curDate.day_of_week();
		Calendar::Date nextDay = curDate;
		nextDay += boost::gregorian::days(1);

		if( this->isWeekDayIncluded( wd + 1))
		{
			// Add the full day to periods.
			periods.merge( Calendar::PeriodSet::traits_type::make_interval( 
				Calendar::Time( curDate), 
				Calendar::Time( nextDay)));
		}
		curDate = nextDay;
	}

	periods.intersect( start, end);

	out.swap( periods);
}

// ---------------------------------------------------------------------------------------------------------------------

bool WeeklyCalendarRule::isWeekDayIncluded( unsigned int weekDay) const
{
	return 0 != (weekdayMap_ & ( 1 << weekDay));
}


} // namespace Model
